﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

using TinyLib.Input;

namespace GodBuilderIdea.Tools
{
    class DrawTool : ITool
    {
        private TileBoard m_tileBoard;
        private Point m_currentTile;

        public DrawTool(TileBoard tileBoard, EnvTile.EnvironmentType type)
        {
            m_tileBoard = tileBoard;
            m_tileType = type;
        }

        public override void MouseLeftClick(int x, int y)
        {
            //change tile types on the board.
            for (int tileIndex = 0; tileIndex < m_tileBoard.Tiles.Count; tileIndex++ )
            {
                if (m_tileBoard.Tiles[tileIndex].Rectangle.Contains(new Point(x, y))
                    && m_tileBoard.Tiles[tileIndex].m_type != m_tileType//m_activePlayer.m_currentTool.m_tileType// m_current_env_type
                    && m_activePlayer.m_actions > 0
                    && m_tileBoard.Tiles[tileIndex].m_type != EnvTile.EnvironmentType.NEXT
                    && m_tileBoard.Tiles[tileIndex].m_type != EnvTile.EnvironmentType.LAVA
                    )
                {
                    if (m_currentTile == null
                        || !m_tileBoard.Tiles[tileIndex].rectangle.Contains(m_currentTile))
                    {
                        m_tileBoard.Tiles[tileIndex].m_changed_type = true;
                        m_tileBoard.Tiles[tileIndex].m_type = m_activePlayer.m_currentTool.m_tileType;

                        if (m_tileBoard.Tiles[tileIndex].m_type == m_activePlayer.m_currentTool.m_tileType)
                        {
                            m_activePlayer.m_actions--;
                        }
                        UpdateEnvMatrix(tileIndex);
                    }

                    m_currentTile = new Point(x, y);
                }

                
            }
        }

        public override void MouseRightClick(int x, int y)
        {
            //Do nothing.
        }

        public void UpdateSurroundingMatrix(int tileIndex)
        {
            //Update N tile
            if ((tileIndex % m_tileBoard.Height) != 0)
            {
                UpdateEnvMatrix(tileIndex - 1);

                //Update NW tile
                if (((int)(tileIndex / m_tileBoard.Height)) != 0)
                    UpdateEnvMatrix(tileIndex - 1 - m_tileBoard.Height);

                //Update NE tile
                if (((int)(tileIndex / m_tileBoard.Height)) != m_tileBoard.Width - 1)
                    UpdateEnvMatrix(tileIndex - 1 + m_tileBoard.Height);

            }

            //Update S tile
            if ((tileIndex % m_tileBoard.Height) != m_tileBoard.Height - 1)
            {
                UpdateEnvMatrix(tileIndex + 1);

                //Update W tile
                if (((int)(tileIndex / m_tileBoard.Height)) != 0)
                    UpdateEnvMatrix(tileIndex + 1 - m_tileBoard.Height);


                //Update E tile
                if (((int)(tileIndex / m_tileBoard.Height)) != m_tileBoard.Width - 1)
                    UpdateEnvMatrix(tileIndex + 1 + m_tileBoard.Height);

            }

            //Update W tile
            if (((int)(tileIndex / m_tileBoard.Height)) != 0)
                UpdateEnvMatrix(tileIndex - m_tileBoard.Height);

            //Update E tile
            if (((int)(tileIndex / m_tileBoard.Height)) != m_tileBoard.Width - 1)
                UpdateEnvMatrix(tileIndex + m_tileBoard.Height);
        }

        public void UpdateEnvMatrix(int tileIndex)
        {
            if (m_tileBoard.Tiles[tileIndex].m_type == EnvTile.EnvironmentType.DEFAULT)
                return;

            int[] numTiles = new int[((int)EnvTile.EnvironmentType.DEFAULT) + 1];
            int numTotalCheckedTiles = 0;
            EnvTile currentTile = m_tileBoard.Tiles[tileIndex];

            //Check N tile
            if ((tileIndex % m_tileBoard.Height) != 0)
            {
                numTiles[(int)m_tileBoard.Tiles[tileIndex - 1].m_type]++;
                numTotalCheckedTiles++;

                //Check NW tile
                if (((int)(tileIndex / m_tileBoard.Height)) != 0)
                {
                    numTiles[(int)m_tileBoard.Tiles[tileIndex - 1 - m_tileBoard.Height].m_type]++;
                    numTotalCheckedTiles++;
                }

                //Check E tile
                if (((int)(tileIndex / m_tileBoard.Height)) != m_tileBoard.Width - 1)
                {
                    numTiles[(int)m_tileBoard.Tiles[tileIndex - 1 + m_tileBoard.Height].m_type]++;
                    numTotalCheckedTiles++;
                }
            }

            //Check S tile
            if ((tileIndex % m_tileBoard.Height) != m_tileBoard.Height - 1)
            {
                numTiles[(int)m_tileBoard.Tiles[tileIndex + 1].m_type]++;
                numTotalCheckedTiles++;

                //Check W tile
                if (((int)(tileIndex / m_tileBoard.Height)) != 0)
                {
                    numTiles[(int)m_tileBoard.Tiles[tileIndex + 1 - m_tileBoard.Height].m_type]++;
                    numTotalCheckedTiles++;
                }

                //Check E tile
                if (((int)(tileIndex / m_tileBoard.Height)) != m_tileBoard.Width - 1)
                {
                    numTiles[(int)m_tileBoard.Tiles[tileIndex + 1 + m_tileBoard.Height].m_type]++;
                    numTotalCheckedTiles++;
                }
            }

            //Check W tile
            if (((int)(tileIndex / m_tileBoard.Height)) != 0)
            {
                numTiles[(int)m_tileBoard.Tiles[tileIndex - m_tileBoard.Height].m_type]++;
                numTotalCheckedTiles++;
            }

            //Check E tile
            if (((int)(tileIndex / m_tileBoard.Height)) != m_tileBoard.Width - 1)
            {
                numTiles[(int)m_tileBoard.Tiles[tileIndex + m_tileBoard.Height].m_type]++;
                numTotalCheckedTiles++;
            }


            //Get the highest number of envtile type surrounding current tile.
            int highestNumOfEnv = 0;
            bool sameNumOfTiles = false;
            int envIndex = -1;
            for (int i = 0; i < numTiles.Length; i++)
            {
                if (numTiles[i] > highestNumOfEnv)
                {
                    highestNumOfEnv = numTiles[i];
                    envIndex = i;
                    sameNumOfTiles = false;
                }
                else if (numTiles[i] == highestNumOfEnv &&
                        numTiles[i] != 0)
                {
                    sameNumOfTiles = true;
                }

            }

            //Check to see if the surrounding tiles matches the current one.
            if (sameNumOfTiles != true &&
                envIndex != -1 &&
                envIndex != ((int)currentTile.m_type) &&
                highestNumOfEnv >= (numTotalCheckedTiles/2) &&
                EnvTile.EnvironmentType.DEFAULT != (EnvTile.EnvironmentType)envIndex)
            {
                //if not...do stuff!
                EnvTile.EnvironmentType currentType = currentTile.m_type;

                switch (currentTile.m_type)
                {
                    case EnvTile.EnvironmentType.DESERT:
                        UpdateDesertType((EnvTile.EnvironmentType)envIndex, currentTile);
                        break;

                    case EnvTile.EnvironmentType.FOREST:
                        break;

                    case EnvTile.EnvironmentType.GRASS:
                        UpdateGrassType((EnvTile.EnvironmentType)envIndex, currentTile);
                        break;

                    case EnvTile.EnvironmentType.LAVA:
                        break;

                    case EnvTile.EnvironmentType.MOUNTAIN:
                        break;

                    case EnvTile.EnvironmentType.SNOW:
                        UpdateSnowType((EnvTile.EnvironmentType)envIndex, currentTile);
                        break;

                    case EnvTile.EnvironmentType.SWAMP:
                        break;

                    case EnvTile.EnvironmentType.WATER:
                        UpdateWaterType((EnvTile.EnvironmentType)envIndex, currentTile);
                        break;

                    default:
                        break;
                }

                //Check if the tile changed type.
                if (currentType != currentTile.m_type)
                {
                    //Update N tile
                    if ((tileIndex % m_tileBoard.Height) != 0)
                    {
                        UpdateEnvMatrix(tileIndex - 1);

                        //Update NW tile
                        if (((int)(tileIndex / m_tileBoard.Height)) != 0)
                            UpdateEnvMatrix(tileIndex - 1 - m_tileBoard.Height);

                        //Update NE tile
                        if (((int)(tileIndex / m_tileBoard.Height)) != m_tileBoard.Width - 1)
                            UpdateEnvMatrix(tileIndex - 1 + m_tileBoard.Height);

                    }

                    //Update S tile
                    if ((tileIndex % m_tileBoard.Height) != m_tileBoard.Height - 1)
                    {
                        UpdateEnvMatrix(tileIndex + 1);

                        //Update W tile
                        if (((int)(tileIndex / m_tileBoard.Height)) != 0)
                            UpdateEnvMatrix(tileIndex + 1 - m_tileBoard.Height);


                        //Update E tile
                        if (((int)(tileIndex / m_tileBoard.Height)) != m_tileBoard.Width - 1)
                            UpdateEnvMatrix(tileIndex + 1 + m_tileBoard.Height);

                    }

                    //Update W tile
                    if (((int)(tileIndex / m_tileBoard.Height)) != 0)
                        UpdateEnvMatrix(tileIndex - m_tileBoard.Height);

                    //Update E tile
                    if (((int)(tileIndex / m_tileBoard.Height)) != m_tileBoard.Width - 1)
                        UpdateEnvMatrix(tileIndex + m_tileBoard.Height);
                }
            }
        }

        public void UpdateDesertType(EnvTile.EnvironmentType type, EnvTile tile)
        {
            switch (type)
            {
                case EnvTile.EnvironmentType.DESERT:
                    break;

                case EnvTile.EnvironmentType.FOREST:
                    break;

                case EnvTile.EnvironmentType.GRASS:
                    break;

                case EnvTile.EnvironmentType.LAVA:
                    tile.ChangeType(EnvTile.EnvironmentType.LAVA);
                    break;

                case EnvTile.EnvironmentType.MOUNTAIN:
                    break;

                case EnvTile.EnvironmentType.SNOW:
                    tile.ChangeType(EnvTile.EnvironmentType.GRASS);
                    break;

                case EnvTile.EnvironmentType.SWAMP:
                    tile.ChangeType(EnvTile.EnvironmentType.SWAMP);
                    break;

                case EnvTile.EnvironmentType.WATER:
                    tile.ChangeType(EnvTile.EnvironmentType.GRASS);
                    break;

                default:
                    break;
            }
        }

        public void UpdateGrassType(EnvTile.EnvironmentType type, EnvTile tile)
        {
            switch (type)
            {
                case EnvTile.EnvironmentType.DESERT:
                    tile.ChangeType(EnvTile.EnvironmentType.DESERT);
                    break;

                case EnvTile.EnvironmentType.FOREST:
                    break;

                case EnvTile.EnvironmentType.GRASS:
                    break;

                case EnvTile.EnvironmentType.LAVA:
                    tile.ChangeType(EnvTile.EnvironmentType.LAVA);
                    break;

                case EnvTile.EnvironmentType.MOUNTAIN:
                    break;

                case EnvTile.EnvironmentType.SNOW:
                    tile.ChangeType(EnvTile.EnvironmentType.SNOW);
                    break;

                case EnvTile.EnvironmentType.SWAMP:
                    break;

                case EnvTile.EnvironmentType.WATER:
                    tile.ChangeType(EnvTile.EnvironmentType.SWAMP);
                    break;

                default:
                    break;
            }
        }

        public void UpdateSnowType(EnvTile.EnvironmentType type, EnvTile tile)
        {
            switch (type)
            {
                case EnvTile.EnvironmentType.DESERT:
                    tile.ChangeType(EnvTile.EnvironmentType.GRASS);
                    break;

                case EnvTile.EnvironmentType.FOREST:
                    break;

                case EnvTile.EnvironmentType.GRASS:
                    break;

                case EnvTile.EnvironmentType.LAVA:
                    tile.ChangeType(EnvTile.EnvironmentType.GRASS);
                    break;

                case EnvTile.EnvironmentType.MOUNTAIN:
                    break;

                case EnvTile.EnvironmentType.SNOW:
                    break;

                case EnvTile.EnvironmentType.SWAMP:
                    break;

                case EnvTile.EnvironmentType.WATER:
                    break;

                default:
                    break;
            }
        }

        public void UpdateWaterType(EnvTile.EnvironmentType type, EnvTile tile)
        {
            switch (type)
            {
                case EnvTile.EnvironmentType.DESERT:
                    break;

                case EnvTile.EnvironmentType.FOREST:
                    tile.ChangeType(EnvTile.EnvironmentType.SWAMP);
                    break;

                case EnvTile.EnvironmentType.GRASS:
                    break;

                case EnvTile.EnvironmentType.LAVA:
                    tile.ChangeType(EnvTile.EnvironmentType.DESERT);
                    break;

                case EnvTile.EnvironmentType.MOUNTAIN:
                    break;

                case EnvTile.EnvironmentType.SNOW:
                    tile.ChangeType(EnvTile.EnvironmentType.SNOW);
                    break;

                case EnvTile.EnvironmentType.SWAMP:
                    break;

                case EnvTile.EnvironmentType.WATER:
                    break;

                default:
                    break;
            }
        } 
    }
}
